#include "st7735.h"
// #include <driver/spi_slave.h>

// static spi_device_handle_t spi;

#include "esp32-hal-spi.h"



spi_t* spi_handler;




void st7735_write_data(uint8_t* data, size_t len);

void st7735_write_byte(uint8_t byte);

void st7735_write_two_byte(uint16_t data);

void st7735_write_cmd(uint8_t cmd);






void st7735_write_cmd(uint8_t cmd)
{
  gpio_write(ST7735_CS, LOW);
  gpio_write(ST7735_DC, LOW);
  // SPI.transfer(&cmd, 1);
  spiWriteByte(spi_handler, cmd);

  // esp_err_t ret;
  // spi_transaction_t t;

  // memset(&t, 0, sizeof(t));
  // t.length = 8;
  // t.tx_buffer = &cmd;
  // ret = spi_device_polling_transmit(spi, &t);  //Transmit!
  // assert(ret == ESP_OK);



  gpio_write(ST7735_CS, HIGH);

}

void st7735_write_data(uint8_t* data, size_t len)
{
  gpio_write(ST7735_DC, HIGH);
  gpio_write(ST7735_CS, LOW);
  // SPI.transfer(data, len);
  // spiWriteByte(spi_handler, cmd);

  for (size_t i = 0;i < len;i++) {
    // st7735_write_byte(data[i]);
    spiWriteByte(spi_handler, data[i]);

  }


  gpio_write(ST7735_CS, HIGH);
  gpio_write(ST7735_DC, LOW);
}



void st7735_write_byte(uint8_t byte)
{
  gpio_write(ST7735_CS, LOW);
  gpio_write(ST7735_DC, HIGH);

  // SPI.transfer(&byte, 1);
  spiWriteByte(spi_handler, byte);

  // esp_err_t ret;
  // spi_transaction_t t;

  // memset(&t, 0, sizeof(t));
  // t.length = 8;
  // t.tx_buffer = &data;
  // ret = spi_device_polling_transmit(spi, &t);  //Transmit!
  // assert(ret == ESP_OK);

  gpio_write(ST7735_CS, HIGH);
}


void st7735_write_two_byte(uint16_t data)
{
  gpio_write(ST7735_CS, LOW);
  gpio_write(ST7735_DC, HIGH);

  // uint8_t high_bit = data >> 8;
  // uint8_t low_bit = data & 0xff;

  // SPI.transfer(&high_bit, 1);
  // SPI.transfer(&low_bit, 1);


  // spiWriteByte(spi_handler, high_bit);
  // spiWriteByte(spi_handler, low_bit);
  // spiW
  spiWriteWord(spi_handler, data);


  // st7735_write_byte(high_bit);
    // st7735_write_byte(low_bit);

  gpio_write(ST7735_CS, HIGH);
  // gpio_write(ST7735_DC, LOW);
}









void st7735_reset()
{
  gpio_write(ST7735_RET, LOW);
  delay(100);
  gpio_write(ST7735_RET, HIGH);
  delay(100);
}


void st7735_hardware_init()
{
  gpio_mode_set(ST7735_DC, OUTPUT);
  gpio_mode_set(ST7735_RET, OUTPUT);
  gpio_mode_set(ST7735_CS, OUTPUT);


  // SPI.begin(ST7735_CLK, 11, ST7735_MOSI, ST7735_CS);
  // SPI.setFrequency(8000000);


  // spi_bus_config_t buscfg = {
  //     .miso_io_num = 11,
  //     .mosi_io_num = ST7735_MOSI,
  //     .sclk_io_num = ST7735_CLK,
  //     .quadwp_io_num = -1,
  //     .quadhd_io_num = -1,
  // };

  // spi_device_interface_config_t devcfg = {
  //     .clock_speed_hz = 10 * 1000 * 1000,
  //     .mode = 3,
  //     .spics_io_num = -1,
  //     .queue_size = 1,
  // };
  // //Initialize the SPI bus
  // ret = spi_bus_initialize(HSPI_HOST, &buscfg, SPI_DMA_CH_AUTO);
  // ESP_ERROR_CHECK(ret);

  // //Attach the LCD to the SPI bus
  // ret = spi_bus_add_device(HSPI_HOST, &devcfg, &spi);
  // ESP_ERROR_CHECK(ret);
  // uint32_t freq = 10 * 1000 * 1000;

  uint32_t div = spiFrequencyToClockDiv(80000000);




  spi_handler = spiStartBus(FSPI, div, SPI_MODE0, SPI_MSBFIRST);




  spiAttachSCK(spi_handler, ST7735_CLK);
  spiAttachMISO(spi_handler, 11);
  spiAttachMOSI(spi_handler, ST7735_MOSI);



  delay(100);

}











void st7735_init()
{
  st7735_hardware_init();
  delay(200);
  st7735_reset();

  st7735_write_cmd(ST7735_SLPOUT);
  delay(120);
  st7735_write_cmd(ST7735_FRMCTR1);
  st7735_write_byte(0x01);
  st7735_write_byte(0x2C);
  st7735_write_byte(0x2D);
  st7735_write_cmd(ST7735_FRMCTR2);
  st7735_write_byte(0x01);
  st7735_write_byte(0x2C);
  st7735_write_byte(0x2D);
  st7735_write_cmd(ST7735_FRMCTR3);
  st7735_write_byte(0x01);
  st7735_write_byte(0x2C);
  st7735_write_byte(0x2D);
  st7735_write_byte(0x01);
  st7735_write_byte(0x2C);
  st7735_write_byte(0x2D);
  st7735_write_cmd(ST7735_INVCTR);
  st7735_write_byte(0x07);
  st7735_write_cmd(ST7735_PWCTR1);
  st7735_write_byte(0xA2);
  st7735_write_byte(0x02);
  st7735_write_byte(0x84);
  st7735_write_cmd(ST7735_PWCTR2);
  st7735_write_byte(0xC5);
  st7735_write_cmd(ST7735_PWCTR3);
  st7735_write_byte(0x0A);
  st7735_write_byte(0x00);
  st7735_write_cmd(ST7735_PWCTR4);
  st7735_write_byte(0x8A);
  st7735_write_byte(0x2A);
  st7735_write_cmd(ST7735_PWCTR5);
  st7735_write_byte(0x8A);
  st7735_write_byte(0xEE);
  st7735_write_cmd(ST7735_VMCTR1);
  st7735_write_byte(0x0E);
  st7735_write_cmd(ST7735_INVERSE ? ST7735_INVON : ST7735_INVOFF);
  st7735_write_cmd(ST7735_COLMOD);
  st7735_write_byte(0x05);
  st7735_write_cmd(ST7735_CASET);
  st7735_write_byte(0x00);
  st7735_write_byte(0x00);
  st7735_write_byte(0x00);
  st7735_write_byte(0x7F);
  st7735_write_cmd(ST7735_RASET);
  st7735_write_byte(0x00);
  st7735_write_byte(0x00);
  st7735_write_byte(0x00);
  st7735_write_byte(0x9F);
  st7735_write_cmd(ST7735_GMCTRP1);
  st7735_write_byte(0x02);
  st7735_write_byte(0x1C);
  st7735_write_byte(0x07);
  st7735_write_byte(0x12);
  st7735_write_byte(0x37);
  st7735_write_byte(0x32);
  st7735_write_byte(0x29);
  st7735_write_byte(0x2D);
  st7735_write_byte(0x29);
  st7735_write_byte(0x25);
  st7735_write_byte(0x2B);
  st7735_write_byte(0x39);
  st7735_write_byte(0x00);
  st7735_write_byte(0x01);
  st7735_write_byte(0x03);
  st7735_write_byte(0x10);
  st7735_write_cmd(ST7735_GMCTRN1);
  st7735_write_byte(0x03);
  st7735_write_byte(0x1D);
  st7735_write_byte(0x07);
  st7735_write_byte(0x06);
  st7735_write_byte(0x2E);
  st7735_write_byte(0x2C);
  st7735_write_byte(0x29);
  st7735_write_byte(0x2D);
  st7735_write_byte(0x2E);
  st7735_write_byte(0x2E);
  st7735_write_byte(0x37);
  st7735_write_byte(0x3F);
  st7735_write_byte(0x00);
  st7735_write_byte(0x00);
  st7735_write_byte(0x02);
  st7735_write_byte(0x10);
  st7735_write_cmd(ST7735_NORON);
  delay(10);
  st7735_write_cmd(ST7735_DISPON);
  delay(10);


  st7735_write_cmd(ST7735_MADCTL);
  st7735_write_byte(0);
  st7735_set_rotation(2);

}


void st7735_set_region(unsigned int x_start, unsigned int y_start, unsigned int x_end, unsigned int y_end)
{
  st7735_write_cmd(0x2a);
  st7735_write_byte(0x02);
  st7735_write_byte(x_start);
  st7735_write_byte(0x02);
  st7735_write_byte(x_end);

  st7735_write_cmd(0x2b);
  st7735_write_byte(0x01);
  st7735_write_byte(y_start);
  st7735_write_byte(0x01);
  st7735_write_byte(y_end);

  st7735_write_cmd(0x2c);

}




//全屏填充函数
void st7735_clear(uint16_t color)
{
  uint8_t i, j;
  st7735_set_region(0, 0, 127, 159);
  for (i = 0;i < 160;i++)
  {
    for (j = 0;j < 128;j++)
    {
      st7735_write_two_byte(color);
    }
  }
}


void st7735_set_rotation(uint8_t rotation)
{
  uint8_t madctl = 0;

  switch (rotation)
  {
  case 0:
    madctl = ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_MODE;
    break;
  case 1:
    madctl = ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_MODE;
    break;
  case 2:
    madctl = ST7735_MADCTL_MODE;
    break;
  case 3:
    madctl = ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_MODE;
    break;
  }

  st7735_write_cmd(ST7735_MADCTL);
  st7735_write_byte(madctl);
}


// ST7735_DrsawRectangle

// void st7735_draw_rectange(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color)
// {
//   static uint8_t buff[ST7735_WIDTH * 2];
//   uint16_t i = 0;

//   for (i = 0; i < width; i++) {
//     buff[i * 2] = color >> 8;
//     buff[i * 2 + 1] = color & 0xFF;
//   }

//   st7735_set_region(x, y, x + width - 1, y + height - 1);
//   st7735_write_cmd(ST7735_RAMWR);
//   // Write the color data
//   for (i = 0; i < height; i++) {
//     st7735_write_data(buff, sizeof(uint16_t) * width);
//   }
// }



void st7735_draw_rectange(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color)
{
  // uint16_t buff[ST7735_WIDTH];
  uint16_t i, j;

  // for (i = 0; i < width; i++) {

  // }

  st7735_set_region(x, y, x + width - 1, y + height - 1);
  st7735_write_cmd(ST7735_RAMWR);

  for (i = 0;i < width;i++) {
    for (j = 0;j < height;j++) {
      st7735_write_two_byte(color);

    }

  }
  // Write the color data
  // for (i = 0; i < height; i++) {
  //   st7735_write_data(buff, sizeof(uint16_t) * width);
  // }
}


void st7735_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
  uint16_t i, j;

  st7735_set_region(x1, y1, x2, y2);
  st7735_write_cmd(ST7735_RAMWR);

  for (i = x1;i < x2;i++) {
    for (j = y1;j <= y2;j++) {
      st7735_write_two_byte(color);
    }
  }

}


void st7735_draw_buffer(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t* color)
{

  uint16_t i, j;

  st7735_set_region(x1, y1, x2, y2);
  st7735_write_cmd(ST7735_RAMWR);

  for (i = x1;i < x2;i++) {
    for (j = y1;j <= y2;j++) {
      st7735_write_two_byte(*color);
      color++;
    }
  }
}